// Static properties used to make application more readable
// These properties represent what part of the UI to monitor
public static var NONE:Number = 0;
public static var TOP_LEFT:Number = 1;		
public static var TOP_RIGHT:Number = 2;		
public static var BOTTOM_RIGHT:Number = 3;		
public static var BOTTOM_LEFT:Number = 4;		
public static var WHOLE:Number = 5;

// Class properties used to calculate positioning and sizing values
private var down:Number = 0;	
private var bottom:Number = 0;	
private var left:Number = 0;
private var right:Number = 0;
private var top:Number = 0;
private var xOffset:Number = 0;
private var yOffset:Number = 0;

// Called when a UI element has been selected and needs to be arranged based on current mouse position
public function arrange( event:Object ):void {
	var sizing:Object = null;

	// The UIObject.mouseMoveSomewhere() method gets called regardless
	// We only want to take any actions if a UI element is currently selected
	if( down != NONE ) {

		// Based on the UI element currently selected, retrieve new sizing information
		switch( down ) {
			case TOP_LEFT:
				sizing = dimension( right, bottom, cvsStage.mouseX, cvsStage.mouseY );
				break;
			case TOP_RIGHT:
				sizing = dimension( left, bottom, cvsStage.mouseX, cvsStage.mouseY );
				break;					
			case BOTTOM_RIGHT:
				sizing = dimension( left, top, cvsStage.mouseX, cvsStage.mouseY );
				break;																						
			case BOTTOM_LEFT:
				sizing = dimension( right, top, cvsStage.mouseX, cvsStage.mouseY );
				break;											
				
			// When the whole area is being moved, no sizing needs to be calculated
			// In place of resizing, move entire area to wherever the mouse is currently
			// Track mouse offset from x, y coordinates to keep mouse in same relative area on rectangle
			case WHOLE:
				sizing = new Object();
				sizing.x = cvsStage.mouseX - xOffset;
				sizing.y = cvsStage.mouseY - yOffset;
				sizing.width = rect.width;
				sizing.height = rect.height;
				break;
		}
		
		// Position the handles to be inline with new sizing or location
		position( sizing.x, sizing.y, sizing.width, sizing.height );										
		
		// Position and size area to conform to handle positioning
		rect.move( sizing.x, sizing.y);
		//rect.setActualSize(sizing.width, sizing.height );
		rect.width = sizing.width;
		rect.height = sizing.height;
		//rect.setSize( sizing.width, sizing.height );				
	}
}

// Called when resizing is in progress and new sizing information is required based on mouse position
public function dimension( left, top, right, bottom ):Object {
	var hold:Number = null;
	var dim:Object = new Object();

	// If the left side of the area has been dragged beyond the right side, then flip the values
	// This is the magic that allows resizing across opposite borders
	if( left > right ) {
		hold = left;
		left = right;
		right = hold;
	}
	
	// Perform the same conmparison and swapping of values for resizing of top and bottom borders
	if( top > bottom ) {
		hold = top;
		top = bottom;
		bottom = hold;
	}

	// Prepare to report on new sizing
	// I opt to store this information on an Object so I can easily return several related values at once
	dim.x = left;
	dim.y = top;			
	dim.width = Math.max( 4.5, right - left );
	dim.height = Math.max( 4.5, bottom - top );			

	// Return the new sizing information
	return dim;
}

// Called when the application is initialized to establish initial positioning of the handle UI elements
public function initApp( event:Object ):void {
	position( rect.x, rect.y, rect.width, rect.height );
}

// Called when the handle UI element need to be reposition due to resize or move
// Expects the upper left x, y coordinates and the width and hieght values
// Only positions the handle UI elements, and does not account for the area rectangle itself
public function position( x:Number, y:Number, width:Number, height:Number ):void {

	// Use the UIObject.move() method for multiple reasons
	// - Abbreviates individual x and y assignments
	// - Allows application to ignore move event that isn't necessary to monitor
	// This ultimately leads to an improvement in performance
	topLeft.move( x - 4.5, y - 4.5 );
	topRight.move( x + width - 4.5, y - 4.5 );
	bottomRight.move( x + width - 4.5, y + height - 4.5);
	bottomLeft.move( x - 4.5, y + height - 4.5 );
}

// Called when a mouse press occurs on a UI element
// Stores initial positioning, sizing and offset data for reference during resizing and positioning
public function start( corner:Number ):void {
	// Track which element is being moved
	down = corner;

	// Track initial positioning and sizing
	left = rect.x;
	top = rect.y;
	right = rect.x + rect.width;
	bottom = rect.y + rect.height;
	
	// Store mouse offset from rectangle origination for reference during move
	xOffset = cvsStage.mouseX - rect.x;
	yOffset = cvsStage.mouseY - rect.y;		
}